package com.feidee.data.report.dao.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.feidee.data.report.constant.Constant;
import com.feidee.data.report.dao.IReportStatusMachine;
import com.feidee.data.report.model.ColumnInfoModel;
import com.feidee.data.report.model.CustomReportModel;
import com.feidee.data.report.model.SqlInfoModel;
import com.feidee.data.report.util.DbOperationUtil;
import com.feidee.data.report.util.ToolUtils;
import org.apache.log4j.Logger;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class ReportStatusMachineImpl implements IReportStatusMachine {

    private static Logger logger = Logger.getLogger(ReportStatusMachineImpl.class);

    private DataSource metadataSource;


    /**
     * 获取当前提交的报表与前一次提交报表元数据的区别
     *
     * @param newCrpm
     * @return 返回状态码
     * "0" 无改动，不需做任务操作
     * "1" 新增报表，全部流程
     * "2" 非新增报表，改动需要执行所有流程 [Mysql类型改变也会全部重跑，一般是结果写入Mysql出错才会更改类型]
     * "3" Mysql注释改变
     * "4" 报表执行周期改变
     * "5" 报表注释改变
     * "6" 实时sql改变,历史sql没改变
     * "7" 历史sql改变，实时sql没改变
     * "8" 报表依赖关系改变
	 * "9" 报表优先级改变
	 * "10" 报表数据源改变
     *
     * 返回值格式：发布状态€状态机状态，第一个状态表示是否发布, 后面的状态即上面描述,用 # 分割
     * 返回的状态机状态是本次提交与上一次提交的比对，同时会综合发布之前多次提交的状态码，写到缓存库中
     */
    public String getStatus( CustomReportModel newCrpm ) {

        String id = newCrpm.getId();
        String report_key = newCrpm.getApplysqlname();
        String metaQuerySql = "select * from custom_report_metadata where id='" + id + "'";
        String pubFlagSql = "select distinct is_enable from report_sql where report_key='" + report_key + "'";
        // 连接数据库执行SQL
        Connection conn = null;
        Statement statement = null;
        ResultSet rs = null;
        //报表元数据存储字段
        String applyName = "";        //报表注释
        String period = "";           //报表执行周期
		String priority = "";         //报表优先级
        String mysqlColumn = "";      //mysql列元数据Json串
        String hivesql = "";          //hivesql数据Json串
	    String reportDependency = ""; //报表依赖
		String dataResources = ""; //数据源
        Map<String, ColumnInfoModel> mysqlColumnInfoMap = new HashMap<String, ColumnInfoModel>(); //Mysql列元数据map结构
        Map<String, SqlInfoModel> hivesqlInfoMap = new HashMap<String, SqlInfoModel>();  //hivesql数据map结构
        String pubFlag = Constant.CR_PUBSTATUS_NO_PUBLISH;     //存储报表否发布,默认为未发布
        String checkStatus = Constant.CR_STATUS_NEW_REPORT; //默认为新增报表状态

        try {
            //获取前一次提交报表的元数据
            conn = metadataSource.getConnection();
            statement = conn.createStatement();
            rs = statement.executeQuery(metaQuerySql);
            if (rs.next()) {
                applyName = rs.getString("applyname");
                period = rs.getString("period");
                priority = rs.getString("priority");
                mysqlColumn = rs.getString("mysqlcolumn");
                hivesql = rs.getString("hivesql");
	            reportDependency = rs.getString("report_dependency");
				dataResources = rs.getString("data_resources");

                Boolean emptyFlag = false;
                String resMsg = "自定义报表 " + newCrpm.getId() + " => " + newCrpm.getApplysqlname() + " ";
                if (!ToolUtils.isNotNull(applyName)) {
                    emptyFlag = true;
                    resMsg += "上一次报表中文注释为空,";
                }
                if (!ToolUtils.isNotNull(period)) {
                    emptyFlag = true;
                    resMsg += "上一次报表执行周期为空,";
                }
				if (!ToolUtils.isNotNull(priority)) {
					emptyFlag = true;
					resMsg += "上一次报表优先级为空,";
				}
                if (!ToolUtils.isNotNull(mysqlColumn)) {
                    emptyFlag = true;
                    resMsg += "上一次报表Mysql列信息为空,";
                }
                if (!ToolUtils.isNotNull(hivesql)) {
                    emptyFlag = true;
                    resMsg += "上一次报表HiveSql信息为空,";
                }
	            if (!ToolUtils.isNotRealNull(reportDependency)) {
		            reportDependency = "";
	            }
				if (!ToolUtils.isNotRealNull(dataResources)) {
					dataResources = "";
				}
                if (emptyFlag) {
                    logger.info(resMsg + "默认为新增报表!");
                    writeStatusToMysql(newCrpm, Constant.CR_STATUS_NEW_REPORT, Constant.CR_PUBSTATUS_NO_PUBLISH);
                    return Constant.CR_PUBSTATUS_NO_PUBLISH + Constant.ERR_MSG_SPLIT_FLAG + Constant.CR_STATUS_NEW_REPORT;
                }
            } else {
                //属于新增的报表
                logger.info("自定义报表 " + newCrpm.getId() + " => " + newCrpm.getApplysqlname() + " 为新增报表!");
                writeNewIdStatusToMysql(newCrpm, Constant.CR_STATUS_NEW_REPORT, Constant.CR_PUBSTATUS_NO_PUBLISH);
                return Constant.CR_PUBSTATUS_NO_PUBLISH + Constant.ERR_MSG_SPLIT_FLAG + Constant.CR_STATUS_NEW_REPORT;
            }

            //初始化Map结构
            initMetadataMap(mysqlColumn, hivesql, mysqlColumnInfoMap, hivesqlInfoMap);

            //查看当前提交的报表是否已经发布
            rs = statement.executeQuery(pubFlagSql);
            if (rs.next()) {
                pubFlag = rs.getString("is_enable");
            }

            logger.info("自定义报表 " + newCrpm.getId() + " ==> " + newCrpm.getApplyname() + " 上次发布标识:" + pubFlag
                    + ",本次提交元数据信息：" + JSON.toJSONString(newCrpm) + " ,上一次元数据信息: applyName:" + applyName
                    + ",period:" + period + ",priority:" + priority + ",mysqlColumnInfo:" + mysqlColumn + ",hivesqlInfo:" + hivesql
		            + ",reportDependency:" + reportDependency+ ",dataResources:" + dataResources);

            //状态比较
            String mysqlCompareRes = compareMysqlInfo(newCrpm.getMysqlColumn(), mysqlColumnInfoMap);
            String hiveCompareRes = compareHiveSql(newCrpm.getHivesql(), hivesqlInfoMap);
            String applynameCompareRes = compareApplyName(newCrpm.getApplyname(), applyName);
            String periodCompareRes = comparePeriod(newCrpm.getPeriod(), period);
			String priorityCompareRes = comparePeriod(newCrpm.getPriority(), priority);
	        String reportDependencyCompareRes = compareReportDependency(newCrpm.getReportDependency(), reportDependency);
			String dataResourcesCompareRes = compareDataResources(newCrpm.getDataResources(), dataResources);
            //将状态机结果和发布状态写入元数据存储表
	        checkStatus = getCurStatus(mysqlCompareRes, hiveCompareRes, applynameCompareRes,
			        periodCompareRes, priorityCompareRes, reportDependencyCompareRes, dataResourcesCompareRes);
	        String multipleStatus = getMultipleStatus(newCrpm, checkStatus);
	        //将综合状态写入Mysql数据库,返回本次校验状态
            writeStatusToMysql(newCrpm, multipleStatus, pubFlag);
        } catch (Exception e) {
            logger.error("自定义报表 " + newCrpm.getId() + " ==> " + newCrpm.getApplyname() + " 获取上一次发布参数失败,", e);
            writeStatusToMysql(newCrpm, Constant.CR_STATUS_NEW_REPORT, Constant.CR_PUBSTATUS_NO_PUBLISH);
            return Constant.CR_PUBSTATUS_NO_PUBLISH + Constant.ERR_MSG_SPLIT_FLAG + Constant.CR_STATUS_NEW_REPORT;
        } finally {
            DbOperationUtil.cleanConnEnv(conn, statement, rs);
        }

        return pubFlag + Constant.ERR_MSG_SPLIT_FLAG + checkStatus;
    }

    /**
     * 拼接元数据Map结构
     *
     * @param mysqlColumn
     * @param hivesql
     * @param mysqlColumnInfoMap
     * @param hivesqlInfoMap
     */
    private void initMetadataMap( String mysqlColumn, String hivesql, Map<String,
            ColumnInfoModel> mysqlColumnInfoMap, Map<String, SqlInfoModel> hivesqlInfoMap ) {
        //拼接MySQL对象Map
        Map<String, JSONObject> mysqlInfoMap = JSON.parseObject(mysqlColumn, Map.class);
        Set<Map.Entry<String, JSONObject>> entries = mysqlInfoMap.entrySet();
        for (Map.Entry<String, JSONObject> entry : entries) {
            ColumnInfoModel columnInfoModel = JSON.parseObject(entry.getValue().toJSONString(), ColumnInfoModel.class);
            mysqlColumnInfoMap.put(entry.getKey(), columnInfoModel);
        }

        //拼接hivesql对象map
        Map<String, JSONObject> sqlInfoMap = JSON.parseObject(hivesql, Map.class);
        entries = sqlInfoMap.entrySet();
        for (Map.Entry<String, JSONObject> entry : entries) {
            SqlInfoModel sqlInfoModel = JSON.parseObject(entry.getValue().toJSONString(), SqlInfoModel.class);
            hivesqlInfoMap.put(entry.getKey(), sqlInfoModel);
        }
    }

    /**
     * 将新增报表信息写入元数据存储表
     *
     * @param crm
     * @return
     */
    public void writeMetadataToMysql( CustomReportModel crm ) {

        Connection conn = null;
        PreparedStatement statement = null;
        String updateSql = "update custom_report_metadata set `period`=?,`mysqlcolumn`=?,`hivesql`=?,`applyname`=?,"
		        + "`report_dependency`=?,`priority`=?,`data_resources`=? where id='" + crm.getId() + "'";

        try {
            conn = metadataSource.getConnection();
            conn.setAutoCommit(false);
            statement = conn.prepareStatement(updateSql);
            statement.setString(1, crm.getPeriod());
            statement.setString(2, JSON.toJSONString(crm.getMysqlColumn()));
            statement.setString(3, JSON.toJSONString(crm.getHivesql()));
            statement.setString(4, crm.getApplyname());
	        statement.setString(5, crm.getReportDependency());
			statement.setString(6, crm.getPriority());
			statement.setString(7, crm.getDataResources());
            statement.addBatch();
            statement.executeBatch();
            conn.commit();
            logger.info("自定义报表 " + crm.getId() + " => " + crm.getApplysqlname()
                    + " 元数据表更新元信息[period,mysqlcolumn,hivesql,applyname,dependency],id:" + crm.getId() + " 成功!");
        } catch (Exception e) {
            logger.error("自定义报表 " + crm.getId() + " => " + crm.getApplysqlname()
                    + " 元数据表更新元信息[period,mysqlcolumn,hivesql,applyname,dependency],id:" + crm.getId() + " 失败,", e);
        } finally {
            DbOperationUtil.cleanConnEnv(conn, statement);
        }
    }

    /**
     * 将新增报表的状态信息写入元数据存储表
     * 仅写入报表Id，报表名称，报表发布状态以及报表校验状态，将period,mysqlcolumn,hivesql,applyname字段置为''，
     * 待本次提交操作执行成功后再写入这四个字段信息。防止提前写入后，改动又执行失败，导致下次提交不能正常执行
     *
     * @param crm
     * @param checkStatus
     * @param pubStatus
     * @return
     */
    private void writeNewIdStatusToMysql( CustomReportModel crm, String checkStatus, String pubStatus ) {

        Connection conn = null;
        PreparedStatement statement = null;
        String updateSql = "insert into custom_report_metadata(`period`,`mysqlcolumn`,`hivesql`,`applyname`," +
                "`report_dependency`,`id`,`applysqlname`,`pubstatus`,`checkstatus`,`priority`,`data_resources`) " +
				"values('','','','','',?,?,?,?,?,?) on duplicate key update `id`=?,`applysqlname`=?," +
                "`pubstatus`=?,`checkstatus`=?,`priority`=?,`data_resources`=?";

        try {
            conn = metadataSource.getConnection();
            conn.setAutoCommit(false);
            statement = conn.prepareStatement(updateSql);
            statement.setString(1, crm.getId());
            statement.setString(2, crm.getApplysqlname());
            statement.setString(3, pubStatus);
            statement.setString(4, checkStatus);
			statement.setString(5, crm.getPriority());
			statement.setString(6, crm.getDataResources());
            statement.setString(7, crm.getId());
            statement.setString(8, crm.getApplysqlname());
            statement.setString(9, pubStatus);
            statement.setString(10, checkStatus);
            statement.setString(11, crm.getPriority());
            statement.setString(12, crm.getDataResources());
            statement.addBatch();
            statement.executeBatch();
            conn.commit();
            logger.info("自定义报表 " + crm.getId() + " => " + crm.getApplysqlname()
                    + " 元数据表新增状态,id:" + crm.getId() + ",状态机结果:" + checkStatus + ",发布状态:"
                    + pubStatus + " 成功!");
        } catch (Exception e) {
            logger.error("自定义报表 " + crm.getId() + " => " + crm.getApplysqlname()
                    + " 元数据表新增状态,id:" + crm.getId() + ",状态机结果:" + checkStatus + ",发布状态:"
                    + pubStatus + " 失败,", e);
        } finally {
            DbOperationUtil.cleanConnEnv(conn, statement);
        }
    }

    /**
     * 将状态写入元数据存储表，直接更新对应报表Id的状态值即可
     *
     * @param crm
     * @param checkStatus
     * @param pubStatus
     * @return
     */
    private void writeStatusToMysql( CustomReportModel crm, String checkStatus, String pubStatus ) {

        Connection conn = null;
        PreparedStatement statement = null;
        String id = crm.getId();
        String updateSql = "update custom_report_metadata set pubstatus=?,checkstatus=? where id='" + id + "'";

        try {
            conn = metadataSource.getConnection();
            conn.setAutoCommit(false);
            statement = conn.prepareStatement(updateSql);
            statement.setString(1, pubStatus);
            statement.setString(2, checkStatus);
            statement.addBatch();
            statement.executeBatch();
            conn.commit();
            logger.info("自定义报表 " + crm.getId() + " => " + crm.getApplysqlname()
                    + " 元数据表更新状态 ,id:" + id + ",状态机结果:" + checkStatus + ",发布状态:"
                    + pubStatus + " 成功!");
        } catch (Exception e) {
            logger.error("自定义报表 " + crm.getId() + " => " + crm.getApplysqlname()
                    + " 元数据表更新状态 ,id:" + id + ",状态机结果:" + checkStatus + ",发布状态:"
                    + pubStatus + " 失败,", e);
        } finally {
            DbOperationUtil.cleanConnEnv(conn, statement);
        }
    }

    /**
     * 获取报表的上一次状态机状态和发布状态
     *
     * @param crpm
     * @return
     */
    public String getMachinePublishStatus( CustomReportModel crpm ) {
        // 连接数据库执行SQL
        Connection conn = null;
        Statement statement = null;
        ResultSet rs = null;
        String statusQuerySql = "select pubstatus,checkstatus from custom_report_metadata where id='" + crpm.getId() + "'";
        String machineStatus = "1";
        String pubStatus = "0";
        try {
            //获取前一次提交报表判断的发布和状态机状态
            conn = metadataSource.getConnection();
            statement = conn.createStatement();
            rs = statement.executeQuery(statusQuerySql);
            if (rs.next()) {
                machineStatus = rs.getString("checkstatus");
                pubStatus = rs.getString("pubstatus");
            }

            logger.info("自定义报表 " + crpm.getId() + " => " + crpm.getApplysqlname()
                    + " 发布时获取状态机结果和前一次发布状态成功,SQL:" + statusQuerySql + ",状态机结果:" + machineStatus
                    + ",发布状态:" + pubStatus);
            return pubStatus + Constant.ERR_MSG_SPLIT_FLAG + machineStatus;
        } catch (Exception e) {
            logger.info("自定义报表 " + crpm.getId() + " => " + crpm.getApplysqlname()
                    + " 发布时获取状态机结果和前一次发布状态异常,SQL:" + statusQuerySql + ",", e);
            return pubStatus + Constant.ERR_MSG_SPLIT_FLAG + machineStatus;
        } finally {
	        DbOperationUtil.cleanConnEnv(conn, statement, rs);
        }

    }

	/**
	 * 获取报表前一次状态机状态
	 *
	 * @param newCrpm
	 * @return
	 */
	public String getBefCheckStatus(CustomReportModel newCrpm) {
		// 连接数据库执行SQL
		Connection conn = null;
		Statement statement = null;
		ResultSet rs = null;
		String statusQuerySql = "select checkstatus from custom_report_metadata where id='" + newCrpm.getId() + "'";
		String machineStatus = "";
		try {
			//获取前一次提交报表判断的发布和状态机状态
			conn = metadataSource.getConnection();
			statement = conn.createStatement();
			rs = statement.executeQuery(statusQuerySql);
			if (rs.next()) {
				machineStatus = rs.getString("checkstatus");
				if (! ToolUtils.isNotNull(machineStatus)) {
					machineStatus = "";
				}
			}

			logger.info("自定义报表 " + newCrpm.getId() + " => " + newCrpm.getApplysqlname()
					+ " 获取前一次状态机状态:" + machineStatus);
			return machineStatus;
		} catch (Exception e) {
			logger.info("自定义报表 " + newCrpm.getId() + " => " + newCrpm.getApplysqlname()
					+ " 获取前一次状态机状态异常" + ",", e);
			return machineStatus;
		} finally {
			DbOperationUtil.cleanConnEnv(conn, statement, rs);
		}
	}

	/**
     * 综合未发布前的所有状态，获取综合状态
	 * (1)如果前一次状态为空或未改动，直接返回本次状态；
	 * (2)如果本次校验为未改动，直接返回前一次状态；
	 * (3)如果之前状态包含本次状态，直接返回；
	 * (4)状态1,2都是执行自定义报表全部流程，所有仅需其中一个状态即可，无需多次加入；
	 * (5)状态1,2都是执行自定义报表全部流程，包含了状态6和状态7的执行流程，所有如果状态已有1或2，状态6,7无需再加入到综合状态；
	 * (6)如果本次状态是6，前一次改动是7，则直接改为状态2，移除之前的状态7，反之相同
	 * (7)除去上述情况，如果之前不包含本次状态，则将本次状态加入到综合状态中
     * @param newCrpm
     * @return
     */
    private String getMultipleStatus(CustomReportModel newCrpm, String checkStatus) {
	    //获取前一次状态
	    String befCheckStatus = getBefCheckStatus(newCrpm);

	    if ("".equals(befCheckStatus) || Constant.CR_STATUS_NO_CHANGE.equals(befCheckStatus)) {
		    return checkStatus;
	    }
	    if (Constant.CR_STATUS_NO_CHANGE.equals(checkStatus)) {
		    return befCheckStatus;
	    }
	    String[] befStatusArray = befCheckStatus.split(Constant.CUSTOM_REPORT_STATUS_SPLIT, -1);
	    List<String> befStatusList = new ArrayList<String>(Arrays.asList(befStatusArray));
	    String[] statusArray = checkStatus.split(Constant.CUSTOM_REPORT_STATUS_SPLIT, -1);
	    for (String status : statusArray) {
		    if (befStatusList.contains(status)) {
			    continue;
		    }
		    if (status.equals(Constant.CR_STATUS_NEW_REPORT) &&
				    befStatusList.contains(Constant.CR_STATUS_CHANGE_NEED_ALL_EXECUTE)) {
			    continue;
		    }
		    if (status.equals(Constant.CR_STATUS_CHANGE_NEED_ALL_EXECUTE) &&
				    befStatusList.contains(Constant.CR_STATUS_NEW_REPORT)) {
			    continue;
		    }
		    if (status.equals(Constant.CR_STATUS_NEW_REPORT) ||
				    status.equals(Constant.CR_STATUS_CHANGE_NEED_ALL_EXECUTE)) {
			    befStatusList.remove(Constant.CR_STATUS_HIVESQL_CHANGE_HISTORYSQL_NOCHANGE);
			    befStatusList.remove(Constant.CR_STATUS_HISTORYSQL_CHANGE_HIVESQL_NOCHANGE);
			    befStatusList.add(status);
		    }
		    if (status.equals(Constant.CR_STATUS_HIVESQL_CHANGE_HISTORYSQL_NOCHANGE) &&
				    befStatusList.contains(Constant.CR_STATUS_HISTORYSQL_CHANGE_HIVESQL_NOCHANGE)) {
			    befStatusList.remove(Constant.CR_STATUS_HISTORYSQL_CHANGE_HIVESQL_NOCHANGE);
				befStatusList.add(Constant.CR_STATUS_CHANGE_NEED_ALL_EXECUTE);
		    }
		    if (status.equals(Constant.CR_STATUS_HISTORYSQL_CHANGE_HIVESQL_NOCHANGE) &&
				    befStatusList.contains(Constant.CR_STATUS_HIVESQL_CHANGE_HISTORYSQL_NOCHANGE)) {
			    befStatusList.remove(Constant.CR_STATUS_HIVESQL_CHANGE_HISTORYSQL_NOCHANGE);
			    befStatusList.add(Constant.CR_STATUS_CHANGE_NEED_ALL_EXECUTE);
		    }
		    if (status.equals(Constant.CR_STATUS_HIVESQL_CHANGE_HISTORYSQL_NOCHANGE) &&
				    (befStatusList.contains(Constant.CR_STATUS_CHANGE_NEED_ALL_EXECUTE) ||
						    befStatusList.contains(Constant.CR_STATUS_NEW_REPORT))) {
			    continue;
		    }
		    if (status.equals(Constant.CR_STATUS_HISTORYSQL_CHANGE_HIVESQL_NOCHANGE) &&
				    (befStatusList.contains(Constant.CR_STATUS_CHANGE_NEED_ALL_EXECUTE) ||
						    befStatusList.contains(Constant.CR_STATUS_NEW_REPORT))) {
			    continue;
		    }
		    if (! befStatusList.contains(status)) {
			    befStatusList.add(status);
		    }
	    }

	    String multiCheckStatus = befStatusList.get(0);
	    for (int i=1; i<befStatusList.size(); i++) {
		    multiCheckStatus += Constant.CUSTOM_REPORT_STATUS_SPLIT + befStatusList.get(i);
	    }
	    logger.info("自定义报表 " + newCrpm.getId() + " => " + newCrpm.getApplysqlname()
			    + " 综合状态:" + multiCheckStatus);
	    return multiCheckStatus;
    }

	/**
	 * 修改报表上次状态机状态,将状态改为空
	 *
	 * @param crpm
	 * @return
	 */
	public void modifyCheckStatus(CustomReportModel crpm) {
		// 连接数据库执行SQL
		Connection conn = null;
		PreparedStatement statement = null;
		String statusQuerySql = "update custom_report_metadata set pubstatus='1',checkstatus='' where id='" + crpm.getId() + "'";
		try {
			//获取前一次提交报表判断的发布和状态机状态
			conn = metadataSource.getConnection();
			statement = conn.prepareStatement(statusQuerySql);
			statement.execute();
			logger.info("自定义报表 " + crpm.getId() + " => " + crpm.getApplysqlname()
					+ " 清空前一次状态机状态成功!");
		} catch (Exception e) {
			logger.info("自定义报表 " + crpm.getId() + " => " + crpm.getApplysqlname()
					+ " 清空前一次状态机状态异常,", e);
		} finally {
			DbOperationUtil.cleanConnEnv(conn, statement);
		}
	}

    /**
     * 状态机判断返回状态[除去新增的状态]
     *
     * @param mysqlCompareRes
     * @param hiveCompareRes
     * @param applynameCompareRes
     * @param periodCompareRes
     * @param dataResourcesCompareRes
	 * @return
     */
    private String getCurStatus(String mysqlCompareRes, String hiveCompareRes, String applynameCompareRes,
								String periodCompareRes, String priorityCompareRes, String reportDependencyCompareRes, String dataResourcesCompareRes) {

        String status = "";

        //Mysql列数量改变、Mysql列名改变、Mysql列主键改变、Mysql列类型
        //HiveSql条数改变、sql源改变、sql类型改变、实时sql和历史sql都变了
        if ("1".equals(mysqlCompareRes) || "2".equals(mysqlCompareRes) || "3".equals(mysqlCompareRes) || "4".equals(mysqlCompareRes)
                || "1".equals(hiveCompareRes) || "2".equals(hiveCompareRes) || "3".equals(hiveCompareRes) || "6".equals(hiveCompareRes)) {
            return Constant.CR_STATUS_CHANGE_NEED_ALL_EXECUTE;
        } else {
            if ("5".equals(mysqlCompareRes)) {      //Mysql列注释改变
                status += Constant.CR_STATUS_MYSQL_COLUMN_COMMENT_CHANGE + Constant.CUSTOM_REPORT_STATUS_SPLIT;
            }
            if ("1".equals(periodCompareRes)) {     //检查报表执行周期是否改变
                status += Constant.CR_STATUS_REPORT_PEROID_CHANGE + Constant.CUSTOM_REPORT_STATUS_SPLIT;
            }
			if ("1".equals(priorityCompareRes)) {     //检查报表优先级是否改变
				status += Constant.CR_STATUS_REPORT_PRIORITY_CHANGE + Constant.CUSTOM_REPORT_STATUS_SPLIT;
			}
            if ("1".equals(applynameCompareRes)) {  //检查报表注释是否改变
                status += Constant.CR_STATUS_REPORT_COMMENT_CHANGE + Constant.CUSTOM_REPORT_STATUS_SPLIT;
            }
            if ("4".equals(hiveCompareRes)) {       //实时sql改变,历史sql没改变
                status += Constant.CR_STATUS_HIVESQL_CHANGE_HISTORYSQL_NOCHANGE + Constant.CUSTOM_REPORT_STATUS_SPLIT;
            }
            if ("5".equals(hiveCompareRes)) {       //历史sql改变，实时sql没改变
                status += Constant.CR_STATUS_HISTORYSQL_CHANGE_HIVESQL_NOCHANGE + Constant.CUSTOM_REPORT_STATUS_SPLIT;
            }
	        if ("1".equals(reportDependencyCompareRes)) {
		        status += Constant.CR_STATUS_REPORT_DEPENDENCY_CHANGE + Constant.CUSTOM_REPORT_STATUS_SPLIT;
	        }
			if ("1".equals(dataResourcesCompareRes)) {
				status += Constant.CR_STATUS_DATA_RESOURCES_CHANGE + Constant.CUSTOM_REPORT_STATUS_SPLIT;
			}
        }

        if (!ToolUtils.isNotNull(status)) {
            return Constant.CR_STATUS_NO_CHANGE;
        }
        status = status.substring(0, status.length() - 1);
        return status;
    }

    /**
     * 检查HiveSql是否改变
     * 0：没有改变
     * 1：HiveSql条数改变
     * 2：sql源改变
     * 3：sql类型改变
     * 4：实时sql改变,历史sql没改变
     * 5：历史sql改变，实时sql没改变
     * 6：实时sql和历史sql都变了
     *
     * @param newHiveSql
     * @param oldHiveSql
     * @return status
     */
    public String compareHiveSql( Map<String, SqlInfoModel> newHiveSql, Map<String, SqlInfoModel> oldHiveSql ) {

        String keyTem = "sql";
        String key;
        SqlInfoModel newSqlInfo;
        SqlInfoModel oldSqlInfo;
        String newSqlContent;
        String oldSqlContent;
        String newSqlHistory;
        String oldSqlHistory;
        String newSqlSource;
        String oldSqlSource;
        String newSqlType;
        String oldSqlType;
        boolean sqlContentFlag = false;
        boolean sqlHistoryFlag = false;
        if (newHiveSql.size() != oldHiveSql.size()) {
            return "1";
        }
        for (int i = 1; i <= newHiveSql.size(); i++) {
            key = keyTem + i;
            newSqlInfo = newHiveSql.get(key);
            oldSqlInfo = oldHiveSql.get(key);
            newSqlSource = newSqlInfo.getSqlSource();
            oldSqlSource = oldSqlInfo.getSqlSource();
            if (!(newSqlSource.equals(oldSqlSource))) {
                return "2";
            }
            newSqlType = newSqlInfo.getSqlType();
            oldSqlType = oldSqlInfo.getSqlType();
            if (!(newSqlType.equals(oldSqlType))) {
                return "3";
            }
            newSqlContent = formatSql(newSqlInfo.getSqlContent());
            oldSqlContent = formatSql(oldSqlInfo.getSqlContent());
            newSqlHistory = formatSql(newSqlInfo.getSqlHistory());
            oldSqlHistory = formatSql(oldSqlInfo.getSqlHistory());
            if (!(newSqlContent.equals(oldSqlContent))) {
                sqlContentFlag = true;
            }
            if (!(newSqlHistory.equals(oldSqlHistory))) {
                sqlHistoryFlag = true;
            }
        }
        if (sqlContentFlag && sqlHistoryFlag) {
            return "6";
        }
        if (sqlContentFlag) {
            return "4";
        }
        if (sqlHistoryFlag) {
            return "5";
        }
        return "0";
    }

    public String formatSql( String sql ) {
        sql = sql.replaceAll("\r\n", " ").replaceAll("\r", " ").replaceAll("\n", " ").replaceAll(" +", " ");
        return sql;
    }

    /**
     * 检查Mysql列信息参数是否改变
     * 0：没有改变
     * 1：Mysql列数量改变
     * 2：Mysql列名改变
     * 3：Mysql列主键改变
     * 4：Mysql列类型
     * 5：Mysql列注释改变
     *
     * @param newMysqlInfo
     * @param oldMysqlInfo
     * @return
     */
    private String compareMysqlInfo( Map<String, ColumnInfoModel> newMysqlInfo, Map<String, ColumnInfoModel> oldMysqlInfo ) {

        //Mysql列数量改变
        if (newMysqlInfo.size() != oldMysqlInfo.size()) {
            return "1";
        }
        //Mysql列名改变
        Set<String> newColumnsSet = newMysqlInfo.keySet();
        Set<String> oldColumnsSet = oldMysqlInfo.keySet();
        for (String newColumn : newColumnsSet) {
            if (!oldColumnsSet.contains(newColumn)) {
                return "2";
            }
        }

        for (String newColumn : newColumnsSet) {
            ColumnInfoModel newColumnInfoModel = newMysqlInfo.get(newColumn);
            ColumnInfoModel oldColumnInfoModel = oldMysqlInfo.get(newColumn);

            //Mysql列主键改变
            if (!newColumnInfoModel.getDimType().equals(oldColumnInfoModel.getDimType())) {
                return "3";
            }

            //Mysql列类型
            if (!newColumnInfoModel.getColumnType().equals(oldColumnInfoModel.getColumnType())) {
                return "4";
            }

            //Mysql列注释改变
            if (!newColumnInfoModel.getColumnValue().equals(oldColumnInfoModel.getColumnValue())) {
                return "5";
            }
        }

        return "0";
    }

    /**
     * 检查报表执行周期是否改变
     * 0：没有改变
     * 1：有改变
     *
     * @param newPeriod
     * @param oldPeriod
     * @return
     */
    private String comparePeriod( String newPeriod, String oldPeriod ) {

        if (newPeriod.equals(oldPeriod)) {
            return "0";
        }
        return "1";
    }

	/**
	 * 检查报表优先级是否改变
	 * 0：没有改变
	 * 1：有改变
	 *
	 * @param newPriority
	 * @param oldPriority
	 * @return
	 */
	private String comparePriority( String newPriority, String oldPriority ) {

		if (newPriority.equals(oldPriority)) {
			return "0";
		}
		return "1";
	}

    /**
     * 检查报表注释是否改变
     * 0：没有改变
     * 1：有改变
     *
     * @param newApplyname
     * @param oldApplyname
     * @return
     */
    private String compareApplyName( String newApplyname, String oldApplyname ) {

        if (newApplyname.equals(oldApplyname)) {
            return "0";
        }
        return "1";
    }

	/**
	 * 检查报表依赖信息是否改变
	 * 0：没有改变
	 * 1：有改变
	 *
	 * @param newReportDependency
	 * @param oldReportDependency
	 * @return
	 */
	private String compareReportDependency( String newReportDependency, String oldReportDependency ) {

		if (newReportDependency.equals(oldReportDependency)) {
			return "0";
		}
		return "1";
	}

	/**
	 * 检查报表依赖数据源是否改变
	 * 0：没有改变
	 * 1：有改变
	 *
	 * @param newDataResources
	 * @param oldDataResources
	 * @return
	 */
	private String compareDataResources( String newDataResources, String oldDataResources ) {

		if (newDataResources.equals(oldDataResources)) {
			return "0";
		}
		return "1";
	}

    public DataSource getMetadataSource() {
        return metadataSource;
    }

    public void setMetadataSource( DataSource metadataSource ) {
        this.metadataSource = metadataSource;
    }
}
